// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.departures

import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.WindowCompat
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Runnable
import xyz.apiote.bimba.czwek.R
import xyz.apiote.bimba.czwek.api.Error
import xyz.apiote.bimba.czwek.databinding.ActivityDeparturesBinding
import xyz.apiote.bimba.czwek.repo.Departure
import xyz.apiote.bimba.czwek.repo.Stop

class DeparturesActivity : AppCompatActivity() {
	private var _binding: ActivityDeparturesBinding? = null
	private val binding get() = _binding!!

	private lateinit var adapter: BimbaDeparturesAdapter

	private val handler = Handler(Looper.getMainLooper())
	private var runnable = Runnable {}

	private var openBottomSheet: DepartureBottomSheet? = null

	private lateinit var viewModel: DeparturesViewModel

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		_binding = ActivityDeparturesBinding.inflate(layoutInflater)
		setContentView(binding.root)

		viewModel = ViewModelProvider(this)[DeparturesViewModel::class.java]

		viewModel.departures.observe(this){stopDepartures ->
			updateItems(stopDepartures.departures, stopDepartures.stop)
			openBottomSheet?.departureID()?.let { adapter.get(it) }?.let { openBottomSheet?.update(it) }
		}
		viewModel.error.observe(this) {
			showError(it)
		}

		binding.collapsingLayout.apply {
			title = getName()
			val tf = ResourcesCompat.getFont(this@DeparturesActivity, R.font.yellowcircle8)
			setCollapsedTitleTypeface(tf)
			setExpandedTitleTypeface(tf)
		}

		binding.departuresRecycler.layoutManager = LinearLayoutManager(this)
		binding.departuresRecycler.addOnScrollListener(
			object : RecyclerView.OnScrollListener() {
				override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
					super.onScrolled(recyclerView, dx, dy)
					val llm = binding.departuresRecycler.layoutManager as LinearLayoutManager
					val dataLength = adapter.itemCount
					if (llm.findLastCompletelyVisibleItemPosition() == dataLength - 1) {
						if (!viewModel.allItemsRequested) {
							viewModel.requestedItemsNumber += 12
							getDepartures()
						}
					}
				}
			}
		)
		adapter = BimbaDeparturesAdapter(layoutInflater, this, listOf()) {
			DepartureBottomSheet(it).apply {
				show(supportFragmentManager, DepartureBottomSheet.TAG)
				openBottomSheet = this
				setOnCancel { openBottomSheet = null }
			}
		}
		binding.departuresRecycler.adapter = adapter
		WindowCompat.setDecorFitsSystemWindows(window, false)
	}

	override fun onResume() {
		super.onResume()
		getDepartures()
	}

	override fun onPause() {
		super.onPause()
		handler.removeCallbacks(runnable)
	}

	private fun getName(): String {
		return when (intent?.action) {
			Intent.ACTION_VIEW -> getCode()
			null -> intent?.extras?.getString("name") ?: ""
			else -> ""
		}
	}

	private fun getCode(): String {
		@Suppress("SpellCheckingInspection") return when (intent?.action) {
			Intent.ACTION_VIEW -> {
				when (intent?.data?.host) {
					"www.peka.poznan.pl" -> intent?.data?.getQueryParameter("przystanek") ?: ""
					"rj.metropoliaztm.pl" -> intent?.data?.lastPathSegment ?: ""
					else -> ""
				}

			}

			null -> intent?.extras?.getString("code") ?: ""
			else -> ""
		}
	}

	private fun getFeedID(): String {
		return when (intent?.action) {
			Intent.ACTION_VIEW -> {
				@Suppress("SpellCheckingInspection") return when (intent?.data?.host) {
					"www.peka.poznan.pl" -> "poznan_ztm"
					"rj.metropoliaztm.pl" -> "gzm_ztm"
					else -> ""
				}
			}

			null -> {
				intent?.extras?.getString("feedID") ?: ""
			}

			else -> ""
		}
	}

	private fun getLine(): String? {
		return when (intent?.action) {
			null -> intent?.extras?.getString("line")
			else -> null
		}
	}

	fun getDepartures() {
		adapter.refreshItems()
		viewModel.getDepartures(this, getFeedID(), getCode(), getLine())
		handler.removeCallbacks(runnable)
		runnable = Runnable { getDepartures() }
		handler.postDelayed(runnable, 30 * 1000)
	}

	private fun showError(error: Error) {
		binding.departuresProgress.visibility = View.GONE
		binding.departuresRecycler.visibility = View.GONE
		binding.errorImage.visibility = View.VISIBLE
		binding.errorText.visibility = View.VISIBLE

		binding.errorText.text = getString(error.stringResource)
		binding.errorImage.setImageDrawable(AppCompatResources.getDrawable(this, error.imageResource))
	}

	private fun updateItems(departures: List<Departure>, stop: Stop) {
		binding.departuresProgress.visibility = View.GONE
		adapter.update(departures)
		binding.collapsingLayout.apply {
			title = stop.name
		}
		if (departures.isEmpty()) {
			binding.errorImage.visibility = View.VISIBLE
			binding.errorText.visibility = View.VISIBLE
			binding.departuresRecycler.visibility = View.GONE

			binding.errorText.text = getString(R.string.no_departures)
			binding.errorImage.setImageDrawable(
				AppCompatResources.getDrawable(
					this, R.drawable.error_search
				)
			)
		} else {
			if (departures.size < viewModel.requestedItemsNumber) {
				viewModel.allItemsRequested = true
			}
			binding.departuresOverlay.visibility = View.GONE
			binding.errorImage.visibility = View.GONE
			binding.errorText.visibility = View.GONE
			binding.departuresRecycler.visibility = View.VISIBLE
		}
		// todo [3.2; traffic] alerts
		// todo [3.2; traffic] stop info
	}
}